import { HttpFetch } from "@/libs/http"
import { GetServerSideProps } from "next"
import { useEffect, useState } from "react"
const useQuery = <T>(http: HttpFetch) => {
    const [data, setData] = useState<T>(null)
    const [err, setErr] = useState(null)
    useEffect(() => {
        http.commit((err, data) => {
            if (err) {
                setErr(err)
                return;
            }
            setData(data)
        })
    }, [])
    return { data, err, loading: !!data === !!err }
}
export default useQuery
const isServerReq = req => !!req ? !req.url.startsWith('/_next') : false;
type createServerSidePropsType = (queryProps: { [k in string]: HttpFetch }, pre?: boolean) => GetServerSideProps
/**
 * 在page页面中构造serverSideProps
 * 若是服务端渲染会预处理完毕
 * 客户端渲染的话将请求包装下，前端loading
 * pre选择是否预渲染，默认为false
 */
export const createServerSideProps: createServerSidePropsType = (queryProps = {}, pre = false) => {
    return async (ctx) => {
        const props: any = {}
        const { req } = ctx
        //是否是服务端
        const isServer = isServerReq(req)
        //在客户端并且不使用预渲染
        if (!isServer && !pre) {
            //将httpFetch包装为字符串相应props
            return {
                props: Object.keys(queryProps).reduce((acc, label) => {
                    acc[label] = { httpFetchJson: HttpFetch.getFetchJson(queryProps[label]) }
                    return acc;
                }, {} as any)
            }
        }
        const cookies = req.cookies

        //在服务端将httpFetch请求完毕后返回props
        for (const key in queryProps) {
            const saveKey = queryProps[key].isSave ? HttpFetch.getFetchId(queryProps[key]) : null
            let err = null;
            const result = await queryProps[key].setCookie(cookies).commit().catch(e => err = e)
            props[key] = {
                result: !!err ? null : result,
                err,
                saveKey,
                httpFetchJson: HttpFetch.getFetchJson(queryProps[key])
            }
        }
        return { props }
    }
}
//处理createServerSideProps返回的props
export const useQueryProps = <T>(props: any) => {
    const [data, setData] = useState<T>( //处理服务端请求
        Object.keys(props).reduce((acc, label) => {
            const { result, saveKey } = props[label]
            if (!result) return acc;
            //服务端错误请求没有处理，若服务端请求err到客户端会再请求一遍。
            HttpFetch.save(saveKey, result)
            acc[label] = result ?? null
            return acc;
        }, {} as any))
    const [err, setErr] = useState(null);
    useEffect(() => {
        let tmp: any = {}
        let err_tmp: any = {}
        //在客户端请求并且有n个请求的话，会进行n次setData or setErr
        for (const key in props) {
            if (!data[key]) {
                const http = HttpFetch.getHttpFetch(props[key].httpFetchJson)
                http.commit((e, d) => {
                    if (!!e) {
                        err_tmp[key] = e
                        setErr({ ...err_tmp })
                        return
                    }
                    tmp[key] = d;
                    setData({ ...tmp })
                })
            }
        }
    }, [props])
    return { data, err, loading: !Object.keys(data).length && !err }
}